package render
{
	import flash.display.Stage;
	import flash.display.Stage3D;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DCompareMode;
	import flash.display3D.Context3DTriangleFace;
	import flash.display3D.Program3D;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	
	import render.display.RenderLayer;
	import render.events.RenderEvent;

	/*
	 *Context3D 申请创建成功
	 */	
	[Event(name="context3DCreate", type="gpuRender.events.Event")]
	
	public class Render extends EventDispatcher
	{
		/**
		 * Stage对象
		 */		
		protected var _stage:Stage;
		protected var _stage3D:Stage3D;	
		protected var _program3D:Program3D;
		protected var _mousePosition:Vector3D = new Vector3D(0.0, 0.0, 0.0);
		/**
		 * 渲染模式
		 */		
		protected var _renderMode:String;
		/**
		 * 渲染帧率
		 */		
		protected var _frameRate:int;
		/**
		 *渲染区域矩形大小 
		 */		
		protected var _renderRectangle:Rectangle;
		/**
		 * Stage3D对象编号
		 */		
		protected var _stageID:int;
		/**
		 *Context3D 对象 
		 */		
		protected var _context3D:Context3D;
		/**
		 *是否硬件加速 
		 */		
		public static var _isHardwareAccelerated:Boolean;
		/**
		 *是否启动错误检查 
		 */		
		protected var _enableErrorChecking:Boolean = false;
		/**
		 *渲染层列表 
		 */		
		protected var _renderLayers:Vector.<RenderLayer>=new Vector.<RenderLayer>();
		
		/**
		 *GPU渲染
		 * @param renderMode 渲染模式
		 * @param frameRate 渲染帧率
		 * @param bounds 渲染区域大小
		 * @param stageID Stage3D对象编号
		 */		
		public function Render(stage:Stage, renderMode:String, frameRate:int = 60, renderRectangle:Rectangle=null, stageID:int = 0)
		{
			_stage=stage;
			_renderMode=renderMode;
			_frameRate=frameRate;
			_renderRectangle=renderRectangle;
			_stageID=stageID;
			_stage.frameRate = frameRate;
			
			if(_stage.stage3Ds[_stageID].context3D)
			{
				__onContext3DCreated(null);
			}
			else
			{
				_stage.stage3Ds[_stageID].addEventListener(Event.CONTEXT3D_CREATE, __onContext3DCreated);
				_stage.stage3Ds[_stageID].addEventListener(ErrorEvent.ERROR, __onContext3DError);
				_stage.stage3Ds[_stageID].requestContext3D(_renderMode);
			}
		}
		
		/**
		 *  Context3D 申请创建成功
		 * @param evt Event
		 * 
		 */		
		protected function __onContext3DCreated(evt:Event):void
		{
			_stage3D=evt.target as Stage3D;
			_stage3D.removeEventListener(Event.CONTEXT3D_CREATE, __onContext3DCreated);
			_stage3D.removeEventListener(ErrorEvent.ERROR, __onContext3DError);
			
			_context3D = _stage3D.context3D;
			_context3D.enableErrorChecking = _enableErrorChecking;
			_context3D.setCulling(Context3DTriangleFace.NONE);
			_context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
			_isHardwareAccelerated = _context3D.driverInfo.toLowerCase().indexOf("software") == -1;
			_program3D=_context3D.createProgram();
			_context3D.setProgram(_program3D);
			resizeStage();
			RenderManager.instance.context3D=_context3D;
			eventListener();
			//发出context3D申请且创建成功事件
			dispatchEvent(new RenderEvent(RenderEvent.CONTEXT3D_CREATE));
		}
		
		/**
		 *事件监听 
		 * 
		 */		
		protected function eventListener():void
		{
			_stage.addEventListener(MouseEvent.CLICK, _onMouseEventHandler);
			_stage.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseEventHandler);
			_stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseEventHandler);
		}
		
		private function _onMouseEventHandler(evt:MouseEvent):void
		{
//			_mousePosition.x = (evt.stageX - (_renderRectangle ? _renderRectangle.x : 0.0)) / camera.sceneWidth * 2.0 - 1.0;
//			_mousePosition.y = -((evt.stageY - (_renderRectangle ? _renderRectangle.y : 0.0)) / camera.sceneHeight * 2.0 - 1.0);
			_mousePosition.z = 0.0;
			_mousePosition.w = 1.0;
			for each(var renderLayer:RenderLayer in _renderLayers)
			{
				renderLayer.processMouseEvent(evt.type, _mousePosition);
			}
		}
		
		/**
		 * Context3D 申请创建错误
		 * @param evt ErrorEvent
		 * 
		 */		
		private function __onContext3DError(evt:ErrorEvent):void
		{
			var stage3D:Stage3D=evt.target as Stage3D;
			stage3D.removeEventListener(Event.CONTEXT3D_CREATE, __onContext3DCreated);
			stage3D.removeEventListener(ErrorEvent.ERROR, __onContext3DError);
			throw new Error("申请Context3D失败，请检查！");
		}
		
		public function resizeStage():void
		{
			var newrRenderRectangle:Rectangle=_renderRectangle!=null ? _renderRectangle : new Rectangle(0, 0, _stage.stageWidth, _stage.stageHeight);
			_stage3D.x = newrRenderRectangle.x;
			_stage3D.y = newrRenderRectangle.y;
			_context3D.configureBackBuffer(newrRenderRectangle.width, newrRenderRectangle.height, 2, true);
		}
		
		/**
		 *增加渲染层 
		 * @param renderLayer 渲染层对象
		 * 
		 */		
		public function addRenderLayer(renderLayer:RenderLayer):void
		{
			_renderLayers.push(renderLayer);
		}
		
		/**
		 *渲染 
		 * 
		 */		
		public function render():void
		{
			_context3D.clear();
			for each(var renderLayer:RenderLayer in _renderLayers)
			{
				renderLayer.render();
			}
			_context3D.present();
		}
		
		/**
		 *资源释放
		 * 
		 */		
		public function dispose():void
		{
			while(_renderLayers && _renderLayers.length>0)
			{
				var renderLayer:RenderLayer=_renderLayers.shift();
				renderLayer.dispose();
				renderLayer=null;
			}
			_renderLayers=null;
			if(_stage)
			{
				_stage.removeEventListener(MouseEvent.CLICK, _onMouseEventHandler);
				_stage.removeEventListener(MouseEvent.MOUSE_DOWN, _onMouseEventHandler);
				_stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseEventHandler);
				
				for(var i:int = 0; i < _stage.stage3Ds.length; i++)
				{
					_stage.stage3Ds[i].removeEventListener(Event.CONTEXT3D_CREATE, __onContext3DCreated);
					_stage.stage3Ds[i].removeEventListener(ErrorEvent.ERROR, __onContext3DError);
				}
				_stage=null;	
			}
			if(_program3D)
			{
				_program3D.dispose();
				_program3D=null;	
			}
			if(_context3D)
			{
				_context3D.dispose();
				_context3D=null;
			}
			_renderRectangle=null;
			_stage3D=null;
			_mousePosition=null;
		}

		/**
		 * Context3D 对象
		 */
		public function get context3D():Context3D
		{
			return _context3D;
		}

		public function get program3D():Program3D
		{
			return _program3D;
		}

		/**
		 * 渲染区域矩形大小
		 */
		public function get renderRectangle():Rectangle
		{
			return _renderRectangle;
		}

		/**
		 * @private
		 */
		public function set renderRectangle(value:Rectangle):void
		{
			_renderRectangle = value;
		}


	}
}